# -*- coding: utf-8 -*-
"""
@Time: 2025/3/24 14:23
@Author: jins
@File: __init__.py.py
@Introduction: 
"""
import time

from const import *
import operator
import inspect
import re
from libs.db2 import OceanDb
from datetime import datetime, timedelta


def assert_equal(argv1, argv2, precision=9, printflag=1, exclude='', failexit=True, failstr=''):
    flag = True
    # 比较两个输入是否相等
    type_argv1 = type(argv1)
    type_argv2 = type(argv2)
    m = None
    frame = inspect.getframeinfo(inspect.currentframe().f_back)[3]
    if frame:
        for line in frame:
            m = re.search(r'assert_equal\s*\((\s*.*?,\s*.*?)\s*\)', line)
            if m:
                name_argv1 = m.group(1).split(',')[0]
                name_argv2 = m.group(1).split(',')[1]
                unequal_str = f'{name_argv1}({argv1} {type_argv1})!={name_argv2}({argv2} {type_argv2})'
                equal_str = f'{name_argv1}({argv1} {type_argv1})=={name_argv2}({argv2} {type_argv2})'
                break
    else:
        unequal_str = f'{argv1}({type_argv1})!={argv2}({type_argv2})'
        equal_str = f'{argv1}({type_argv1})=={argv2}({type_argv2})'
    unequal_str += f' {failstr}'
    try:
        if type_argv1 in [int, float] and type_argv2 in [int, float]:
            assert int(abs(argv1 - argv2) * (10 ** precision)) <= 1, unequal_str
        elif type_argv1 == dict and type_argv2 == dict:
            assert cmpdicts(argv1, argv2, exclude, printflag), unequal_str
        elif type_argv1 == list and type_argv2 == list:
            assert operator.eq(argv1, argv2), unequal_str
        else:
            assert argv1 == argv2, unequal_str
        if printflag == 1:
            printcolor(equal_str, ColorSet.OK)
    except AssertionError:
        if failexit:
            assert False, unequal_str
        else:
            printcolor(unequal_str, ColorSet.FAIL)
            flag = False
            # ignorebug(inspect.stack()[1])
    return flag


def cmpdicts(dct0, dct1, exclude='', printflag=1):
    if type(exclude) != list: exclude = [exclude]
    diffs = set()
    keys = set(list(dct0.keys()) + list(dct1.keys()))
    result = True
    for k in keys:
        if printflag:
            print(
                f'cmp dictkey={k} in dct0 {type(dct0.get(k))}, {dct0.get(k)} == dct1 {type(dct1.get(k))} , {dct1.get(k)} ')
        if type(dct0.get(k)) not in (float, int, str, list, bool, int, datetime, datetime.datetime) \
                and dct0.get(k) is not None and k not in exclude:
            result = cmpdicts(dct0.get(k).__dict__, dct1.get(k).__dict__, exclude)
        else:
            if operator.eq(dct0.get(k), dct1.get(k)) is False and k not in exclude:
                diffs.add(k)
                result = False
    if diffs != set():
        print('diffs=', diffs)
    return result


def printcolor(printstr, color=ColorSet.CLOSE):
    if color == ColorSet.OK:  # 绿色：成功
        print('\033[1;32;48m' + printstr + '\033[0m')
    elif color == ColorSet.FAIL:  # 红色：失败
        print('\033[1;31;48m' + printstr + '\033[0m')
    elif color == ColorSet.WARN:  # 黄色：警告
        print('\033[1;33;48m' + printstr + '\033[0m')
    elif color == ColorSet.TIPS:  # 蓝色：提示
        print('\033[1;34;48m' + printstr + '\033[0m')
    else:  # 恢复
        print(printstr)


def check_busi(db, reqSerial, CHANNEL_BUSI_STATUS, CENTER_BUSI_STATUS, UPPS_TRANS_STATUS, BUSI_REFUSE_CODE,
               SEND_RECV_FLAG='0'):
    # 检查业务流水表字段状态
    if reqSerial == 1:
        res = db.query(
            f"SELECT CHANNEL_BUSI_STATUS,CENTER_BUSI_STATUS,UPPS_TRANS_STATUS,BUSI_REFUSE_CODE,HOST_BUSI_STATUS,SEND_HOST_SERIAL FROM (select * from BUPPS_BUSI_SERIAL where SEND_RECV_FLAG = '{SEND_RECV_FLAG}' order by CREATE_DATETIME desc) where ROWNUM <= 1")
    else:
        res = db.query(
            f"SELECT CHANNEL_BUSI_STATUS,CENTER_BUSI_STATUS,UPPS_TRANS_STATUS,BUSI_REFUSE_CODE,HOST_BUSI_STATUS,SEND_HOST_SERIAL FROM BUPPS_BUSI_SERIAL WHERE REQ_SERIAL = '{reqSerial}'")
    print('开始检查业务流水表...')
    assert_equal(res['CHANNEL_BUSI_STATUS'], CHANNEL_BUSI_STATUS)
    assert_equal(res['CENTER_BUSI_STATUS'], CENTER_BUSI_STATUS)
    assert_equal(res['UPPS_TRANS_STATUS'], UPPS_TRANS_STATUS)
    assert_equal(res['BUSI_REFUSE_CODE'], BUSI_REFUSE_CODE)
    return res['SEND_HOST_SERIAL']


def check_none_busi(db, reqSerial, UPPS_TRANS_STATUS, SEND_RECV_FLAG='0'):
    # 检查非账务流水表字段状态
    if reqSerial == 1:
        res = db.query(
            f"SELECT UPPS_TRANS_STATUS FROM (select * from bupps_noncapital_trans_info where SEND_RECV_FLAG = '{SEND_RECV_FLAG}' order by CREATE_DATETIME desc) where ROWNUM <= 1")
    else:
        res = db.query(
            f"SELECT UPPS_TRANS_STATUS FROM bupps_noncapital_trans_info WHERE REQ_SERIAL = '{reqSerial}'")
    print('开始检查业务流水表...')
    assert_equal(res['UPPS_TRANS_STATUS'], UPPS_TRANS_STATUS)
    # return res['SEND_HOST_SERIAL']


def check_host(db, host_id=0, CURR_CORE_STATUS=0, correct=False, SEND_RECV_FLAG='0'):
    # 检查核心表字段状态
    if not correct:
        res = db.query(f"select CURR_CORE_STATUS from BUPPS_HOST_SERIAL where SEND_HOST_SERIAL = '{host_id}'")
    else:
        res = db.query(
            f"select CURR_CORE_STATUS from (select * from BUPPS_HOST_SERIAL where SEND_RECV_FLAG = '{SEND_RECV_FLAG}' order by CREATE_DATETIME desc) where ROWNUM <= 1")
    print('开始检查核心流水表...')
    if isinstance(CURR_CORE_STATUS, str):
        assert_equal(res['CURR_CORE_STATUS'], CURR_CORE_STATUS)
    elif isinstance(CURR_CORE_STATUS, tuple):
        assert res['CURR_CORE_STATUS'] in CURR_CORE_STATUS


def check_resp(resp, resp_code, resp_msg=None):
    # 检查返回体字段
    resp_body = resp.json()['bupps']['resp']['head']
    print(f"\n返回渠道{resp_body['respCode']=}")
    print(f"返回渠道{resp_body['respMsg']=}")
    print('\n开始检查http返回信息...')
    assert_equal(resp.status_code, 200)
    assert_equal(resp_body['respCode'], resp_code)
    if resp_msg:
        assert resp_msg in resp_body['respMsg']


def modify_mock_to_success(db):
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '00000',HOST_TRANS_STATUS = '1',RESP_MSG = '交易成功' where ACCT = '{ACCT.TIME_OUT}'")


def modify_mock_to_fail(db):
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99999',HOST_TRANS_STATUS = '2',RESP_MSG = '交易失败' where ACCT = '{ACCT.TIME_OUT}'")


def get_oriBusiReqNo(db, reqSerial):
    res = db.query(f"SELECT BUSI_REQ_NO FROM BUPPS_BUSI_SERIAL WHERE REQ_SERIAL = '{reqSerial}'")
    return res['BUSI_REQ_NO']


def modify_mock_to_success_2(db):
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '00000',HOST_TRANS_STATUS = '1',RESP_MSG = '交易成功' where ACCT = '{ACCT.FAIL}'")


def modify_mock_to_timeout_2(db):
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99998',HOST_TRANS_STATUS = '3',RESP_MSG = '交易超时' where ACCT = '{ACCT.FAIL}'")


def restore_mock(db=OceanDb()):
    print("开始恢复mock挡板信息。。。")
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '00000',HOST_TRANS_STATUS = '1',RESP_MSG = '交易成功' where ACCT in ('{ACCT.SUCCESS}','{ACCT.CUPS_SUCCESS}')")
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99999',HOST_TRANS_STATUS = '2',RESP_MSG = '交易失败' where ACCT = '{ACCT.FAIL}'")
    db.execute_sql(
        f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99998',HOST_TRANS_STATUS = '3',RESP_MSG = '交易超时' where ACCT = '{ACCT.TIME_OUT}'")


def clear_limit(db=OceanDb()):
    print("开始清除限额登记表！")
    db.execute_sql("delete from LMT_LIMIT_BOOK")


def change_mock(status, acct, db=OceanDb()):
    if str(status) == '1':
        sql = f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '00000',HOST_TRANS_STATUS = '1',RESP_MSG = '交易成功' where ACCT = '{acct}'"
        printcolor(f"账号{acct}已经修改为核心返回成功", ColorSet.WARN)
    elif str(status) == '2':
        sql = f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99999',HOST_TRANS_STATUS = '2',RESP_MSG = '交易失败' where ACCT = '{acct}'"
        printcolor(f"账号{acct}已经修改为核心返回失败", ColorSet.WARN)
    elif str(status) == '3':
        sql = f"update BUPPS_BAFFLE_HOST_ACCOUNT set RESP_CODE = '99998',HOST_TRANS_STATUS = '3',RESP_MSG = '交易超时' where ACCT = '{acct}'"
        printcolor(f"账号{acct}已经修改为核心返回超时", ColorSet.WARN)
    else:
        assert False, '核心状态填写有误'
    db.execute_sql(sql)


def get_ori_data(json_data, db=OceanDb()):
    req_serial = json_data['bupps']['req']['head']['reqSerial']
    res = db.query(f"select MSG_KEY from BUPPS_BUSI_SERIAL where REQ_SERIAL = '{req_serial}'")
    return req_serial, res['MSG_KEY'] if res else None


def get_new_json(pre_data, data_new):
    data_new['bupps']['req']['body']['oriReqSerial'] = get_ori_data(pre_data)[0]
    data_new['bupps']['req']['body']['oriMsgKey'] = get_ori_data(pre_data)[1]
    return data_new


def get_old_date(days=30):
    current_date = datetime.now()
    thirty_days_ago = current_date - timedelta(days=days)
    formatted_date = thirty_days_ago.strftime('%Y%m%d')
    return formatted_date


def random_grantcode(db=OceanDb()):
    grant_code = random.randint(100000, 999999)
    sql = f"update BUPPS_BAFFLE_HOST_ACCOUNT set CARD_INFO = '{grant_code}' where ACCT in ('{ACCT.SUCCESS}','{ACCT.FAIL}','{ACCT.TIME_OUT}')"
    db.execute_sql(sql)
    return grant_code


def wait_and_countdown(seconds: int):
    if not isinstance(seconds, int) or seconds <= 0:
        raise ValueError("等待时间必须为正整数")
    for remaining in range(seconds, 0, -1):
        print(f"倒计时 {remaining} 秒...")
        time.sleep(1)  # 暂停 1 秒
    print("倒计时结束！")


def wait_reversal(seconds=WAIT_REVERSAL_TIME, action='冲正'):
    print(f'开始等待{action}，时间为{seconds}s...')
    wait_and_countdown(seconds)


if __name__ == '__main__':
    # get_ori_data()
    random_grantcode()
